import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter_deer/database/tables.dart';
import 'package:flutter_deer/util/socket/BaseMdcControl.dart';
import 'package:flutter_deer/util/socket/socket_client_manager.dart';
import 'package:injectable/injectable.dart';
import 'package:rxdart/rxdart.dart';

@singleton
class MdcHbJsonControlImpl extends BaseMdcControl {
  static const String _mdcTag = '[mdc_tag_hb_json] ';
  final SocketClientManager _socketClientManager = SocketClientManager();
  final _subscriptions = CompositeSubscription();

  @override
  void initAndStart(String pzIPv4, int uPort) {
    for (int i = 0; i <= 15; i++) {
      _socketClientManager.addClient(pzIPv4, uPort + i);
    }
    // _socketClientManager.addClient(pzIPv4, uPort);
    // 只执行一次
    startLoop();
  }

  final AppOrderBean state = AppOrderBean();
  final AppOrderBean order = AppOrderBean();
  final Map<int, String> msgMap = {};
  final Map<int, int> mapNzlMdcNo = {};
  final List<MdcSetPrcNzlCmdBeanPrcOil> listPrcOil = [];

  // 解析数据，处理
  void parseData(int mdcNo, dynamic data) {
    // 提取 cmdType
    final cmdType = data['cmdType'] as int;
    // 根据 cmdType 执行相应的操作
    switch (cmdType) {
      case 111:
        state
          ..mdcNo = mdcNo
          ..sta = (data['sta'] is int ? data['sta'] : 0) as int
          ..nzl = (data['nzl'] is int ? data['nzl'] : 0) as int
          ..prc = (data['prc'] is int ? data['prc'] : 0) as int
          ..vol = (data['qty'] is int ? data['qty'] : 0) as int
          ..mny = (data['mny'] is int ? data['mny'] : 0) as int
        ;
        stateStreamController.add(state);
        mapNzlMdcNo[state.nzl] = mdcNo;
        sendDataToClient(mdcNo, '''{"cmdType":111,"ret":1}''');
        // 111 状态更新，需要更新价格
        if (state.nzl > 0 && state.sta == 1) {
          final itemPrc = listPrcOil.firstWhere((element) => element.nzl == state.nzl, orElse: () => MdcSetPrcNzlCmdBeanPrcOil());
          final mdc = mapNzlMdcNo[state.nzl] ?? 0;
          if (itemPrc.nzl > 0 && itemPrc.prc > 0 && mdcNo == mdc) {
            sendDataToClient(mdcNo, '''{"cmdType":113,"nzl":${itemPrc.nzl},"prc":${itemPrc.prc}}''');
          }
        }
      case 112:
        AppOrderBean.fromJsonHbOrder(order, data, mdcNo);
        mapNzlMdcNo[order.nzl] = mdcNo;
        orderStreamController.add(order);
        // 返回响应
        sendDataToClient(mdcNo, '''{"cmdType":112,"time":"${data['time']}","vTot":${data['vTot']},"nzl":${order.nzl},"ret":1}''');
        //4、去重入库
        AppOrderBean.insertOrder(order);
        break;
      case 113:
        sendDataToClient(mdcNo, '''{"cmdType":113,"ret":1}''');
        for (final prcOil in listPrcOil) {
          if (prcOil.nzl > 0 && mdcNo == (mapNzlMdcNo[prcOil.nzl] ?? 0)) {
            debugPrint('[setPrice success] mdcNo: $mdcNo, nzl: ${prcOil.nzl}, prc: ${prcOil.prc}');
            prcOil.prc = 0;
          }
        }
        break;
    }
  }

  // 用于标记循环是否正在运行
  bool _isLoopRunning = false;

  // 用于启动循环
  void startLoop() {
    if (_isLoopRunning) {
      return;
    }
    _isLoopRunning = true;

    // 监听连接状态
    _subscriptions.add(_socketClientManager.connectionStateStream.listen((message) {
      mdcStateStreamController.add(message);
    }));

    // 监听数据接收
    _subscriptions.add(_socketClientManager.dataStream.listen((intStr) {
      // 处理数据
      try {
        final data = jsonDecode(intStr.value);
        parseData(intStr.key, data);
      } catch (e) {
        debugPrint('$_mdcTag---> form server: $e');
      }
    }));
  }

  // 用于停止循环
  void stopLoop() {
    if (!_isLoopRunning) {
      return;
    }
    _isLoopRunning = false;
  }

  /// 发送数据到client
  void sendDataToClient(int mdcNo, String data) {
    for (final client in _socketClientManager.clients.values) {
      if (client.getIndexMdc() == mdcNo) {
        client.sendDataString(data);
        return;
      }
    }
  }

  @override
  void clickCallBackNzlAll() {}

  @override
  void delThisMdc(String pzIPv4, int uPort) {
    _socketClientManager.disconnectAll();
  }

  @override
  void getAllPumpCode() {}

  @override
  void queryTTC(int chlNo) {}

  @override
  void refreshMachineTime() {}

  @override
  void setGunPriceByGunNo(List<MdcSetPrcNzlCmdBeanPrcOil> list) {
    listPrcOil.clear();
    listPrcOil.addAll(list);

    for (final item in list) {
      if (item.nzl > 0) {
        final mdcNo = mapNzlMdcNo[item.nzl] ?? 0;
        if (mdcNo > 0 && item.prc > 0) {
          sendDataToClient(mdcNo, '''{"cmdType":113,"nzl":${item.nzl},"prc":${item.prc}}''');
        }
      }
    }

  }

  @override
  void dispose() {
    super.dispose();
    stopLoop();
    _subscriptions.dispose();
  }
}
